package cool.houge.pig.infra.web;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.google.common.collect.ImmutableMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Web 错误响应.
 *
 * @author KK (kzou227@qq.com)
 */
public class Problem {

  /** 错误码. */
  private int code;
  /** 错误标题. */
  private String title;
  /** 错误详细描述. */
  private String detail;
  /** 请求 URL. */
  private String path;
  /** 请求的 HTTP 方法. */
  private String method;
  /** 堆栈. */
  private Object stacktrace;
  /** 参数. */
  private ImmutableMap<String, Object> parameters;

  private Problem(
      int code,
      String title,
      String detail,
      String path,
      String method,
      Object stacktrace,
      ImmutableMap<String, Object> parameters) {
    this.code = code;
    this.title = title;
    this.detail = detail;
    this.path = path;
    this.method = method;
    this.stacktrace = stacktrace;
    this.parameters = parameters;
  }

  public int getCode() {
    return code;
  }

  public String getTitle() {
    return title;
  }

  public String getDetail() {
    return detail;
  }

  public String getPath() {
    return path;
  }

  public String getMethod() {
    return method;
  }

  public Object getStacktrace() {
    return stacktrace;
  }

  @JsonAnyGetter
  public Map<String, Object> getParameters() {
    return parameters;
  }

  public static class Builder {

    private int code;
    private String title;
    private String detail;
    private String path;
    private String method;
    private Object stacktrace;
    private Map<String, Object> parameters;

    public Builder code(int code) {
      this.code = code;
      return this;
    }

    public Builder title(String title) {
      this.title = title;
      return this;
    }

    public Builder detail(String detail) {
      this.detail = detail;
      return this;
    }

    public Builder path(String path) {
      this.path = path;
      return this;
    }

    public Builder method(String method) {
      this.method = method;
      return this;
    }

    public Builder stacktrace(Object stacktrace) {
      this.stacktrace = stacktrace;
      return this;
    }

    public Builder parameters(Map<String, Object> parameters) {
      this.parameters = parameters;
      return this;
    }

    public Builder parameter(String key, Object value) {
      if (this.parameters == null) {
        this.parameters = new LinkedHashMap<>();
      }
      this.parameters.put(key, value);
      return this;
    }

    /** @return */
    public Problem build() {
      return new Problem(
          code, title, detail, path, method, stacktrace, ImmutableMap.copyOf(parameters));
    }
  }

  /** @return */
  public static Builder builder() {
    return new Builder();
  }
}
